package com.free.semantic.common;

import com.free.semantic.core.IClone;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class RelationItem implements IClone<RelationItem> {

    private RelationInstance parentInstance;

    private int parentInstanceID;

    private String name;

    /**
     * 来源事物
     */
    private List<RangeObj> sourceObjectList;

    /**
     * 目标事物
     */
    private RangeObj destObject;

    /**
     * 版本
     */
    private int version;

    public Range getObjectRange(String objectName) {
        List<RangeObj> all = new ArrayList<>(sourceObjectList);
        all.add(destObject);
        for (RangeObj rangeObj : all) {
            if (rangeObj.getObjectName().equals(objectName)) {
                return rangeObj.getRange();
            }
        }
        throw new IllegalArgumentException(String.format("名为：%s的事物不存在", objectName));
    }

    public List<String> getSourceObjList() {
        List<String> objLs = new ArrayList<>();
        for (RangeObj rangeObj : sourceObjectList) {
            objLs.add(rangeObj.getObjectName());
        }
        return objLs;
    }

    public String getDestObj() {
        return destObject.getObjectName();
    }

    public Range getSourceObjectRange(String objectName) {
        List<RangeObj> all = new ArrayList<>(sourceObjectList);
        for (RangeObj rangeObj : all) {
            if (rangeObj.getObjectName().equals(objectName)) {
                return rangeObj.getRange();
            }
        }
        throw new IllegalArgumentException(String.format("名为：%s的事物不存在", objectName));
    }

    public boolean containObj(String objName) {
        return sourceObjectList.stream().anyMatch(obj -> obj.getObjectName().equals(objName))
                || destObject.getObjectName().equals(objName);
    }

    public int getSourceSize() {
        return this.sourceObjectList.size();
    }

    public void reNameObjName(String sourceName, String updateName) {
        List<RangeObj> all = new ArrayList<>(sourceObjectList);
        all.add(destObject);
        for (RangeObj rangeObj : all) {
            if (rangeObj.getObjectName().equals(sourceName)) {
                rangeObj.setObjectName(updateName);
            }
        }
    }

    @Override
    public String toString() {
        return String.format("[%s]:%s->%s", convertToStr(name), convertToStr(sourceObjectList),
                convertToStr(Ls.of(destObject)));
    }

    private String convertToStr(String relationName) {
        if (relationName == null) {
            return "";
        }
        return relationName;
    }

    public static RelationItem parseFromStr(String relationStr) {
        String[] sourceAndDest = relationStr.split("->");
        assert sourceAndDest.length == 2;

        String[] nameAndSource = sourceAndDest[0].split(":");
        String[] source = null;
        String name = "";
        if (nameAndSource.length == 2) {
            name = extractContentInBrackets(nameAndSource[0]);
            String sourceStrLs = extractContentInSmallBrackets(nameAndSource[1]);
            source = sourceStrLs.split(",");
        } else {
            String sourceStrLs = extractContentInSmallBrackets(nameAndSource[0]);
            source = sourceStrLs.split(",");
        }
        List<RangeObj> rangeObjs = new ArrayList<>();
        for (String s : source) {
            rangeObjs.add(RangeObj.parse(s));
        }
        RelationItem relationItem = new RelationItem();
        relationItem.setName(name);
        relationItem.setSourceObjectList(rangeObjs);
        relationItem.setDestObject(RangeObj.parse(sourceAndDest[1]));
        return relationItem;
    }

    public static String extractContentInBrackets(String input) {
        // 正则表达式：匹配外层的中括号及其内容
        String regex = "^\\[(.*)]$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        if (matcher.matches()) {
            // 返回中括号中间的内容
            return matcher.group(1);
        } else {
            // 如果没有匹配到中括号，返回 null
            return null;
        }
    }

    public static String extractContentInSmallBrackets(String input) {
        if (input != null && input.startsWith("(") && input.endsWith(")")) {
            return input.substring(1, input.length() - 1);
        }
        return input;
    }

    private String getStr(List<RangeObj> sourceObjectList) {
        return sourceObjectList.stream().map(RangeObj::getObjectName).sorted(String::compareTo).collect(Collectors.joining(","));
    }

    private String getUniqueStr(RelationItem item) {
        return String.format("%s_%s", getStr(item.getSourceObjectList()), getStr(Ls.of(item.getDestObject())));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        RelationItem that = (RelationItem) o;
        return getUniqueStr(this).equals(getUniqueStr(that));
    }

    @Override
    public int hashCode() {
        return getUniqueStr(this).hashCode();
    }

    private String convertToStr(List<RangeObj> sourceObjectList) {
        if (sourceObjectList.size() == 1) {
            return String.format("%s", sourceObjectList.stream().map(RangeObj::toString).collect(Collectors.joining(",")));

        } else {
            return String.format("(%s)", sourceObjectList.stream().sorted().map(RangeObj::toString).collect(Collectors.joining(",")));
        }
    }

    @Override
    public RelationItem clone() {
        RelationItem relationItem = new RelationItem();
        relationItem.setName(this.getName());
        relationItem.setSourceObjectList(cloneObj(this.sourceObjectList));
        relationItem.setDestObject(this.destObject.clone());
        if (parentInstance != null) {
            relationItem.parentInstanceID = parentInstance.getInstanceID();
        } else {
            relationItem.parentInstanceID = this.parentInstanceID;
        }
        return relationItem;
    }

    private List<RangeObj> cloneObj(List<RangeObj> source) {
        return source.stream().map(RangeObj::clone).collect(Collectors.toList());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public RelationInstance getParentInstance() {
        return parentInstance;
    }

    public void setParentInstance(RelationInstance parentInstance) {
        this.parentInstance = parentInstance;
    }

    public int getParentInstanceID() {
        return parentInstanceID;
    }

    public void setParentInstanceID(int parentInstanceID) {
        this.parentInstanceID = parentInstanceID;
    }

    public List<RangeObj> getSourceObjectList() {
        return sourceObjectList;
    }

    public void setSourceObjectList(List<RangeObj> sourceObjectList) {
        this.sourceObjectList = sourceObjectList;
    }

    public RangeObj getDestObject() {
        return destObject;
    }

    public void setDestObject(RangeObj destObject) {
        this.destObject = destObject;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

}
